package com.want.register;

import com.want.annotation.WantClient;
import com.want.client.Client;
import com.want.client.WantLoadBalanceClient;
import com.want.proxy.JDKWantProxyCreator;
import com.want.service.ServiceInfo;
import lombok.Data;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;

/**
 * @author WangZhiJian
 * @since 2021/12/6 0006
 */
@Data
public class WantClientFactoryBean implements FactoryBean<Object>, ApplicationContextAware {
    /**
     * 类型
     */
    private Class<?> type;
    /**
     * 实例
     */
    private Object instance;

    private ApplicationContext applicationContext;

    public WantClientFactoryBean() {
    }

    public WantClientFactoryBean(Class<?> type, Object instance) {
        this.type = type;
        this.instance = instance;
    }

    @Override
    public Object getObject() throws Exception {
        return createInstance();
    }

    private Object createInstance() {
        Client client = applicationContext.getBean(Client.class);
        ServiceInfo serviceInfo = extractServerInfo(type);
        // 创建代理类,并将实例放入factoryBean
        if(StringUtils.hasText(serviceInfo.getUri())){
            if(client instanceof WantLoadBalanceClient){
                client = ((WantLoadBalanceClient) client).getDelegate();
            }
        }
        instance = JDKWantProxyCreator.getInstance().createProxy(type,client,serviceInfo);
        return instance;
    }

    @Override
    public Class<?> getObjectType() {
        return type;
    }

    /**
     * 提取服务器信息
     *
     * @param type
     * @return
     */
    private ServiceInfo extractServerInfo(Class<?> type) {
        ServiceInfo serverInfo = new ServiceInfo();
        // 获取注解
        WantClient annotation = type.getAnnotation(WantClient.class);
        // 从uri和serviceName 初始化最基础的basePath
        serverInfo.setServiceName(annotation.serviceName());
        serverInfo.setUri(annotation.uri());
        // 如果还有后续path,则追加到basePath后方
        serverInfo.setNextPath(annotation.path());
        return serverInfo;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
